//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package main

import (
	"fmt"
	"io"

	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/project_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/metric_serv"
	"atomgit.com/openlinksaas/api-server/webhook_serv"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

func runWebServer(httpPort uint16, logger *zap.Logger, exitChan chan error) {
	s := gin.New()
	s.Use(gin.Recovery())
	s.POST("/webhook/:projectId/:eventSourceId", func(c *gin.Context) {
		processWebHook(c, logger)
	})
	s.GET("/apptoken/:token", processAppToken)
	s.POST("/usertoken", processUserToken)
	err := s.Run(fmt.Sprintf(":%d", httpPort))
	if err != nil {
		exitChan <- err
	}
}

func processWebHook(c *gin.Context, logger *zap.Logger) {
	projectId := c.Param("projectId")
	eventSourceId := c.Param("eventSourceId")
	defer c.Request.Body.Close()
	payload, err := io.ReadAll(c.Request.Body)
	if err != nil {
		metric_serv.HttpCount.WithLabelValues("webhook", "500").Inc()
		c.Status(500)
		return
	}
	err = webhook_serv.Dispatch(projectId, eventSourceId, c.Request.Header, payload, logger)
	if err != nil {
		metric_serv.HttpCount.WithLabelValues("webhook", "500").Inc()
		c.Status(500)
		return
	}
	metric_serv.HttpCount.WithLabelValues("webhook", "200").Inc()
	c.Status(200)
}

type AppTokenInfo struct {
	ProjectId       string `json:"projectId"`
	ProjectName     string `json:"projectName"`
	UserId          string `json:"userId"`
	UserDisplayName string `json:"userDisplayName"`
}

func processAppToken(c *gin.Context) {
	token := c.Param("token")

	tokenItem, ok := dao.CacheDao.GetAppToken(c, token)
	if !ok {
		metric_serv.HttpCount.WithLabelValues("apptoken", "404").Inc()
		c.String(404, "app token not exist")
		return
	}
	projectItem, err := project_dao.ProjectInfoDao.Get(c, tokenItem.ProjectId)
	if err != nil {
		metric_serv.HttpCount.WithLabelValues("apptoken", "500").Inc()
		c.String(500, fmt.Sprintf("ERR\n%s", err.Error()))
		return
	}
	exist, err := project_dao.MemberInfoDao.Exist(c, tokenItem.ProjectId, tokenItem.UserId)
	if err != nil {
		metric_serv.HttpCount.WithLabelValues("apptoken", "500").Inc()
		c.String(500, fmt.Sprintf("ERR\n%s", err.Error()))
		return
	}
	if !exist {
		metric_serv.HttpCount.WithLabelValues("apptoken", "500").Inc()
		c.String(500, "ERR\nuser is not project member")
		return
	}
	userInfo, err := user_dao.UserInfoDao.Get(c, tokenItem.UserId)
	if err != nil {
		metric_serv.HttpCount.WithLabelValues("apptoken", "500").Inc()
		c.String(500, fmt.Sprintf("ERR\n%s", err.Error()))
		return
	}
	metric_serv.HttpCount.WithLabelValues("apptoken", "200").Inc()
	c.JSON(200, &AppTokenInfo{
		ProjectId:       projectItem.ProjectId,
		ProjectName:     projectItem.BasicInfo.ProjectName,
		UserId:          userInfo.UserId,
		UserDisplayName: userInfo.BasicInfo.DisplayName,
	})
}

type UserTokenInfo struct {
	UserId          string `json:"userId"`
	UserName        string `json:"userName"`
	UserDisplayName string `json:"userDisplayName"`
}

func processUserToken(c *gin.Context) {
	token := c.PostForm("token")
	userId, ok := dao.CacheDao.GetUserOnetimeToken(c, token)
	if !ok {
		metric_serv.HttpCount.WithLabelValues("usertoken", "500").Inc()
		c.String(500, "ERR\ntoken not exist")
		return
	}
	userItem, err := user_dao.UserInfoDao.Get(c, userId)
	if err != nil {
		metric_serv.HttpCount.WithLabelValues("usertoken", "500").Inc()
		c.String(500, fmt.Sprintf("ERR\n%s", err.Error()))
		return
	}
	metric_serv.HttpCount.WithLabelValues("usertoken", "200").Inc()
	c.JSON(200, &UserTokenInfo{
		UserId:          userItem.UserId,
		UserName:        userItem.UserName,
		UserDisplayName: userItem.BasicInfo.DisplayName,
	})
}
